/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.rengy.isql;

import cn.hutool.core.bean.BeanUtil;
import cn.rengy.util._StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanWrapper;
import org.springframework.jdbc.core.StatementCreatorUtils;
import org.springframework.jdbc.core.namedparam.AbstractSqlParameterSource;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * from bean properties of a given JavaBean object. The names of the bean
 * properties have to match the parameter names.
 *
 * <p>Uses a Spring BeanWrapper for bean property access underneath.
 *
 * @author Thomas Risberg
 * @author Juergen Hoeller
 * @since 2.0
 * @see BeanWrapper
 */
@Slf4j
public class _BeanPropertySqlParameterSource extends AbstractSqlParameterSource {


	@Nullable
	private String[] propertyNames;

	private Map<String,Object> beanMap;

	/**
	 * Create a new BeanPropertySqlParameterSource for the given bean.
	 * @param object the bean instance to wrap
	 */
	public _BeanPropertySqlParameterSource(Object object) {
		beanMap=BeanUtil.beanToMap(object);
		propertyNames=StringUtils.toStringArray(this.beanMap.keySet());
	}


	@Override
	public boolean hasValue(String paramName) {

		return this.beanMap.containsKey(paramName)||this.beanMap.containsKey(_StrUtil.reverse(paramName));
	}

	@Override
	@Nullable
	public Object getValue(String paramName) throws IllegalArgumentException {
		if(!this.beanMap.containsKey(paramName)){
			String otherParamName=_StrUtil.reverse(paramName);
			if(this.beanMap.containsKey(otherParamName)){
				paramName=otherParamName;
			}
		}
		Object paramValue=this.beanMap.get(paramName);
		//空字符串执行sql报错
		if(paramValue!=null&&paramValue instanceof String&&((String)paramValue).length()==0) {
			paramValue=null;
		}
		return paramValue;
	}

	private String getParamName(String paramName){
		if(!this.beanMap.containsKey(paramName)){
			String otherParamName=_StrUtil.reverse(paramName);
			if(this.beanMap.containsKey(otherParamName)){
				paramName=otherParamName;
			}
		}
		return paramName;
	}
	/**
	 * Derives a default SQL type from the corresponding property type.
	 * @see StatementCreatorUtils#javaTypeToSqlParameterType
	 */
	@Override
	public int getSqlType(String paramName) {
		paramName=getParamName(paramName);
		Class<?> propType=null;
		Object value=getValue(paramName);
		if(value!=null){
			propType=value.getClass();
		}
		return StatementCreatorUtils.javaTypeToSqlParameterType(propType);
	}

	@Override
	@Nullable
	public String[] getParameterNames() {
		return propertyNames;
	}


	public String toString(){
		return beanMap.toString();
	}
}
